#!/usr/local/bin/perl -w

#############################################################################
## $Id: Perldocs.pm 15616 2013-04-01 21:55:11Z spadkins $
#############################################################################
## (c) 2002 Stephen Adkins <spadkins@gmail.com>
## This is free software, available under the same terms as Perl itself.
#############################################################################

=head1 NAME

perldocs - generates cross-referenced Perl documentation for multiple modules

=head1 SYNOPSIS

  # Command Line usage
  perldocs
  perldocs -targetdir=htdocs -targeturl=http://localhost/pub/perl

  # Perl API (i.e. used within "perldocs")
  use Devel::Perldocs;
  Devel::Perldocs->generate();       # use all default values

  # OR

  %conf = (
      targetdir => "htdocs",
      targeturl => "http://localhost/pub/perl",
  );
  Devel::Perldocs->generate(\%conf); # use customized values

=head1 DESCRIPTION

The "perldocs" program is a documentation generator for Perl code.

The "perldocs" program itself is only a thin command-line wrapper for
the Devel::Perldocs module which does all of the hard work.

The "perldocs" program is different than the "perldoc" program distributed
with Perl.  The "perldoc" program returns documentation from a single file.
The "perldocs" program creates documentation which shows the interrelationships
between files.

=head1 COMMAND USAGE

=head2 Command Line Options

The program is run as

  perldocs [-option=value]

where any number of options may be given, and the available options are
"targetdir", "targeturl", "lib", and "installed".

  perldocs
  perldocs -targetdir=htdocs -targeturl=/pub/p5ee/software/htdocs -lib=lib -installed=0

Defaults:
  targetdir=$HOME/public_html/perl
  targeturl=http://localhost/~yourusername/perl
  lib=
  installed=1

=head1 DETAILED DESCRIPTION

The "perldocs" program is a perl program which
analyzes all installed perl code, infers what distribution
each module is in, and creates sitewide, cross-referenced perl documentation.

Just download the distribution, run "perldocs", and then 
visit "http://localhost/~yourusername/perl" to see documentation for all 
of the perl modules the administrator has installed on your system
(presumably using CPAN.pm).  It's supposed to be that easy!

So fundamentally, "perldocs" is a wrapper around the Pod2HTML stuff.

Then it starts getting creative by parsing the source files to discern
function/method signatures, parameter and return types, and inheritance
hierarchies.

This all happens from *existing sources* without requiring them to do
any special extra documentation tags.
However, there are many ways to do things in Perl, and not everyone
will use the standard perl idioms for parameter declaration.
Invariably, the heuristics
employed to try to determine valid method signatures (etc.) will come up
short and
sometimes be in error.  This is where "perldocs" lets the code author 
override the (perhaps mistakenly) implied metadata with explicit metadata
using specially formatted POD tags.

Furthermore, perldocs creates a page for each module and distribution
showing documentation compliance metrics.
This scoring system could be used to focus 
efforts on which distributions/modules needed more documentation work.

Then perldocs also writes the code metadata to easily parsable files
(Data::Dumper perl code) so that programmers may examine it at runtime.

=head1 DOCUMENTATION USAGE

=head2 Frames and Navigation

The "perldocs" output is inspired by (and similar to) the output of "javadoc",
but its capabilities are customized particularly to the needs of Perl and of
CPAN.

The standard view is from a web browser using HTML frames.
Two frames on the left assist in navigation, while the main frame on the right
displays the body of the documentation.

The upper left frame is called the "contentsFrame".  It always contains
a high level index of groups of modules for which documentation is available.
Selecting a module group will cause the complete list of modules in that 
module group to be shown in the frame below it.

The lower left frame is called the "listFrame".  It always contains a
list of modules from a particular module group.  Selecting a module will
cause the module documentation to be displayed in the main frame to the
right.

The main frame on the right is called the "viewFrame".  It may display
the "Site Summary", a "Distribution Summary" (with Modules divided into
Module Groups), or a "Module Document" (the augmented output of pod2html).

  +-------------------+-------------------------------------------+
  |                   |                                           |
  |   contentsFrame   |                                           |
  |                   |                                           |
  +-------------------+                                           |
  |                   |                 viewFrame                 |
  |                   |                                           |
  |     listFrame     |                                           |
  |                   |                                           |
  |                   |                                           |
  +-------------------+-------------------------------------------+

The top of each document that appears in the "viewFrame" will contain a
navigation menu which allows the user to navigate to a related page of
documentation.

=head1 INTERNALS

=head2 Generated Files

For the overall Site, the following files are generated.

  site/frameset.html  # the outer frameset (also as index.html)
  site/contents.html  # list of module groups    [contentsFrame]
  site/list.html      # list of modules and docs [listFrame]
  site/view.html      # summary of module groups [viewFrame]
  site/view-isa.html  # inheritance tree         [viewFrame]
  site/view-use.html  # dependency tree          [viewFrame]

For each Distribution in the Site, the following files are generated.

  distribution/${dist}/frameset.html  # the outer frameset (also as index.html)
  distribution/${dist}/contents.html  # list of module groups    [contentsFrame]
  distribution/${dist}/list.html      # list of modules and docs [listFrame]
  distribution/${dist}/view.html      # summary of modules       [viewFrame]
  distribution/${dist}/view-isa.html  # inheritance tree         [viewFrame]
  distribution/${dist}/view-use.html  # dependency tree          [viewFrame]

For each Module in the Distribution, the following files are generated.

  module/${module}/${modulepath}-frameset.html # contents      [contentsFrame]
  module/${module}/${modulepath}.html     # API documentation  [viewFrame]
  module/${module}/${modulepath}-isa.html # inheritance tree   [viewFrame]
  module/${module}/${modulepath}-use.html # dependency tree    [viewFrame]

=head2 Heading Menus

At the top of each page which is meant to view in the viewFrame, there is
a heading menu with the following.

   Site   Distribution   Module-Group   Module  :  Doc   Use   ISA

This represents a 2-dimensional grid of possible documents, so two of the elements
will always be highlighted.  The rest will all be available links.

                  Use    ISA    Doc
   Site            X      X      X
   Distribution    X      X      X
   Module          X      X     POD

The meanings of these documents are as follows.

   Site (a given set of directories in @INC)
                  Use   - global distribution-dependency tree of all distributions
                  ISA   - global inheritance tree for all modules in all distributions
                  Doc   - summary doc for the installation
   Distribution (a distribution (Pkg-0.20.tar.gz) as installed from CPAN)
                  Use   - distribution-dependency tree of this distribution
                  ISA   - inheritance tree including ancestors/descendents of modules in distribution
                  Doc   - summary doc for the distribution
   Module (a single module or file of documentation)
                  Use   - module-dependency tree of this module
                  ISA   - inheritance tree including ancestors/descendents of this module
                  Doc   - POD doc for the module

=head1 DEVELOPMENT INFORMATION

=head2 Metadata

The metadata to be gleaned from the source code is as follows.

   $metadata->{distfile}{$distfile}{distribution}

   $metadata->{file}{$file}{primary_module}
   $metadata->{file}{$file}{module}{$module}

   $metadata->{distribution}{$distribution}
   $metadata->{distribution}{$distribution}{version}
   $metadata->{distribution}{$distribution}{requirements}
   $metadata->{distribution}{$distribution}{design}
   $metadata->{distribution}{$distribution}{files}
   $metadata->{distribution}{$distribution}{autoload_files}
   $metadata->{distribution}{$distribution}{shlib_files}
   $metadata->{distribution}{$distribution}{man_files}
   $metadata->{distribution}{$distribution}{modules}
  
   $metadata->{modulegroup}{$modulegroup}
   $metadata->{modulegroup}{$modulegroup}{description}
   $metadata->{modulegroup}{$modulegroup}{requirements}
   $metadata->{modulegroup}{$modulegroup}{design}
   $metadata->{modulegroup}{$modulegroup}{podmodule}
   $metadata->{modulegroup}{$modulegroup}{modules}
   $metadata->{modulegroup}{$modulegroup}{module}{$module}{description}
   $metadata->{modulegroup}{$modulegroup}{module}{$module}{podmodule}
  
   $metadata->{module}{$module}
   $metadata->{module}{$module}{file}
   $metadata->{module}{$module}{parent}
   $metadata->{module}{$module}{parents}
   $metadata->{module}{$module}{children}
   $metadata->{module}{$module}{modulegroup}
   $metadata->{module}{$module}{podmodule}
   $metadata->{module}{$module}{name}
   $metadata->{module}{$module}{synopsis}
   $metadata->{module}{$module}{description}
   $metadata->{module}{$module}{throws}
   $metadata->{module}{$module}{since}
   $metadata->{module}{$module}{deprecated_since}
   $metadata->{module}{$module}{deprecated_discontinue}
   $metadata->{module}{$module}{authors}
   $metadata->{module}{$module}{author}{$author}{email}
   $metadata->{module}{$module}{license}
   $metadata->{module}{$module}{see_also}
  
   $metadata->{module}{$module}{method}{$method}
   $metadata->{module}{$module}{method}{$method}{doc}
   $metadata->{module}{$module}{method}{$method}{visibility}
   $metadata->{module}{$module}{method}{$method}{signatures}
   $metadata->{module}{$module}{method}{$method}{param}{$param}
   $metadata->{module}{$module}{method}{$method}{param}{$param}{type}
   $metadata->{module}{$module}{method}{$method}{param}{$param}{inout}
   $metadata->{module}{$module}{method}{$method}{return}{$return}
   $metadata->{module}{$module}{method}{$method}{return}{$return}{type}
   $metadata->{module}{$module}{method}{$method}{throws}
   $metadata->{module}{$module}{method}{$method}{since}
   $metadata->{module}{$module}{method}{$method}{deprecated_since}
   $metadata->{module}{$module}{method}{$method}{deprecated_discontinue}
   $metadata->{module}{$module}{method}{$method}{sample_usage}

=head2 Logic Flow

  Reads $config file to set values
  Reads Perl code installed in @INC and in $lib
  Reads perl metadata from $metadir
  Writes perl metadata to $metadir
  Writes temporary files (i.e. used by DocSet) to $extsrcdir
  use TemplateToolkit to create output in $targetdir using $templatedir
  [future? (alternative)] Run DocSet to create output in $targetdir using $templatedir

  perldocs
    sets default values for configurable variables
    overrides those values from $HOME/.perldocs.conf
    overrides those values from the command line
    call Devel::Perldocs->generate(\%conf)
  Devel::Perldocs->generate()
    # use one of the following methods
    Devel::Perldocs->generate_standard()
    *or* Devel::Perldocs->generate_from_templates()
    *or* Devel::Perldocs->generate_docset()
           set up the $extsrcdir
           write the DocSet config file
           invoke DocSet with docset_build (passing a DocSet config file)

The DocSet distribution uses the "docset_build" program to build the document
set based on configuration files.  I haven't yet figured out how to set up
the configuration files, so this is not fully implemented.  However, I've
documented my understanding of the internal flow of DocSet here so that I
can pick up where I left off when I get back around to it.

  docset_build
    Create the PS/PDF DocSet
    DocSet::RunTime::registers_reset();
    my $docset = DocSet::DocSet::PSPDF->new($config_file); # defined in DocSet::DocSet
      $docset->init($config_file);                         # defined in DocSet::DocSet::PSPDF
    $docset->set_dir(abs_root => ".");
    $docset->scan;
    $docset->render;
  Create the HTML DocSet
    my $docset = DocSet::DocSet::HTML->new($config_file);  # defined in DocSet::DocSet
      $docset->init($config_file);                         # defined in DocSet::DocSet::HTML
    $docset->set_dir(abs_root => ".");
    $docset->scan;
      $docset->docset_scan_n_cache($reldir, $hidden);
      $docset->chapter_scan_n_cache($reldir, $hidden);
      $docset->link_scan_n_cache($link, $hidden);
      $docset->scan_copy_the_rest();
    $docset->render;

  DocSet::Config
    DocSet::DocSet
      DocSet::DocSet::HTML
      DocSet::DocSet::PSPDF

  DocSet::Doc
    DocSet::Source::HTML
      DocSet::Doc::HTML2HTML
        DocSet::Doc::HTML2HTMLPS
    DocSet::Source::POD
      DocSet::Doc::POD2HTML
      DocSet::Doc::POD2HTMLPS
    DocSet::Source::Text
      DocSet::Doc::Text2HTML

  $docset->scan();
  $docset->render();
    for my $obj ($self->stored_objects) {
      $obj->render($cache);
    }

=cut

package Devel::Perldocs;

use strict;
use warnings;

use Date::Format;
use File::Basename;
use File::Path qw(mkpath);
use Devel::Metadata;
use Pod::Html;

# a token constructor.
# they're all static/module methods anyway.

sub new {
    my ($this, $conf) = @_;
    my $module = ref($this) || $this;
    my $self = {};
    bless $self, $module;
    $conf = {} if (!$conf);
    $self->{conf} = $conf;
    $self->set_defaults();

    my $verbose = $conf->{verbose};

    if ($conf->{lib}) {
        unshift(@INC, split(/[, ]+/, $conf->{lib}));
    }

    #open(STDERR, "> perldocs.log");
    my $dmd = Devel::Metadata->new($conf);
    $self->{metadata} = $dmd;
    print "Metadata read...\n" if ($verbose);

    my ($distributions, $distribution, @distributions, @modules);

    $distributions = $conf->{distributions};
    if ($distributions && $distributions ne "all") {
        @distributions = split(/[, ]+/,$distributions);
        $self->{distributions} = \@distributions;
    }
    else {
        @distributions = (sort $dmd->distributions());
        unshift(@distributions, "site");
        push(@distributions, "unknown");
        $self->{distributions} = \@distributions;
    }
    if ($verbose) {
        my $num_distributions = $#distributions + 1;
        my $dist_list = join(" ", @distributions);
        if (length($dist_list) > 80) {
            $dist_list = substr($dist_list, 0, 80) . "...";
        }
        print "$num_distributions Distributions Found: [$dist_list]\n";
    }

    if ($#distributions > -1 && $distributions[0] eq "site") {
        @modules = $dmd->modules();
        $self->{modules} = \@modules;
    }
    else {
        foreach $distribution (@distributions) {
            push(@modules, $dmd->modules($distribution));
        }
        $self->{modules} = \@modules;
    }

    $self;
}

sub set_defaults {
    my ($self, $conf) = @_;
    $conf = $self->{conf} if (!$conf && ref($self));
    return if (!$conf);
    my $username = getpwuid($<);
    #$conf->{config}        ||= "$ENV{HOME}/.perldocs.conf";
    $conf->{lib}           ||= "";
    $conf->{installed}     ||= 1;
    $conf->{method}        ||= "standard";
    $conf->{metadir}       ||= "$ENV{HOME}/.perldocs/meta";
    $conf->{extsrcdir}     ||= "$ENV{HOME}/.perldocs/src";
    $conf->{targetdir}     ||= "$ENV{HOME}/public_html/perl";
    $conf->{targeturl}     ||= "http://localhost/~$username/perl";
    $conf->{resourcedir}   ||= "/usr/local/share/perldocs";
    $conf->{templatedir}   ||= "/usr/local/share/perldocs/template";  # from_templates() and docset() only
    $conf->{verbose}       ||= 1;
    $conf->{sitetitle}     ||= "Perl Installed";
    $conf->{colorscheme}   ||= "red";
    $conf->{bgcolor}       ||= "";
    $conf->{menubgcolor}   ||= "";
    $conf->{vividbgcolor}  ||= "";
    $conf->{washedbgcolor} ||= "";
    $conf->{linkcolor}     ||= "";
    $conf->{activecolor}   ||= "";
}

sub generate {
    my ($self, $conf) = @_;
    $conf = $self->{conf} if (!$conf && ref($self));
    $conf = {} if (!$conf);
    if (! $conf->{method} || $conf->{method} eq "standard") {
        $self->generate_standard($conf);
    }
    elsif ($conf->{method} eq "template") {
        $self->generate_from_templates($conf);
    }
    #elsif ($conf->{method} eq "docset") {
    #    $self->generate_docset($conf);
    #}
    else {
        $self->generate_standard($conf);
    }
    print "Errors and Warnings written to perldocs.log\n" if ($conf->{verbose});
}

sub generate_standard {
    my ($self, $conf) = @_;

    ##########################################################
    # initialize variables
    ##########################################################
    $conf->{datetime} = time2str("%C", time());
    $self->init_colorscheme($conf);

    ##########################################################
    # initialize directories
    ##########################################################
    my $resourcedir = $conf->{resourcedir};
    my $metadir     = $conf->{metadir};
    my $extsrcdir   = $conf->{extsrcdir};
    my $targetdir   = $conf->{targetdir};
    my $targeturl   = $conf->{targeturl};
    my $verbose     = $conf->{verbose};

    mkpath($metadir)   if (! -d $metadir);
    mkpath($extsrcdir) if (! -d $extsrcdir);
    mkpath($targetdir) if (! -d $targetdir);

    ##########################################################
    # vars
    ##########################################################
    my $dmd           = $self->{metadata};
    my @distributions = @{$self->{distributions}};
    my @modules       = @{$self->{modules}};

    ##########################################################
    # initialize files in html directory
    ##########################################################
    $self->write_style_sheet($conf);  # write the CSS file

    if (-d $resourcedir) {
        system("cp -r $resourcedir/* $targetdir");
        print "Resources copied from [$resourcedir] to [$targetdir]\n" if ($conf->{verbose});
    }

    ##########################################################
    # write_docs()
    ##########################################################
    $self->write_frameset("site");
    $self->write_contents("site");
    $self->write_list("site", "all");

    #$self->write_list_any(\@distributions);
    $self->write_view_a("site", "all", "All Distributions");
    $self->write_view_tree();       # writes all trees
    $self->write_view_use();        # writes all uses

    my ($distribution);
    foreach $distribution (@distributions) {
        $self->write_list("distribution", $distribution);
        print "Write Distribution List [$distribution]\n" if ($verbose);
    }

    #$self->write_view_metrics();    # writes all metrics

    ##########################################################
    # write_pods()
    ##########################################################
    my ($module, $pod_file, $pod_dir, $html_file, $html_dir);
    my ($relative_root);
    foreach $module (@modules) {

        $pod_file = "$extsrcdir/lib/$module.pm";
        $pod_file =~ s!::!/!g;
        $pod_dir = dirname($pod_file);
        mkpath($pod_dir) if (! -d $pod_dir);

        $html_file = "$targetdir/module/$module.html";
        $html_file =~ s!::!/!g;
        $html_dir = dirname($html_file);
        mkpath($html_dir) if (! -d $html_dir);

        $dmd->write_module_ext_pod($module, $pod_file);
        printf("Wrote Module Extended Pod: %-32s => [$pod_file]\n","[$module]") if ($verbose);

        $relative_root = $module;
        $relative_root =~ s/[^:]+/../g;
        $relative_root =~ s!:+!/!g;
        if (-f $pod_file) {
            pod2html(
               "--podroot=$extsrcdir/lib",
               "--htmlroot=$targeturl/module",
               "--htmldir=$targeturl/module",
               "--podpath=.",
               "--recurse",
               "--title=Module - $module",
               "--css=$relative_root/style.css",
               "--infile=$pod_file",
               "--outfile=$html_file");
    
            $self->fix_module_html($conf, $module, $html_file, $relative_root);
            printf("Wrote Module %-32s => [$html_file]\n","[$module]") if ($verbose);
        }
    }
}

sub generate_from_templates {
    my ($self, $conf) = @_;

    ##########################################################
    # initialize variables
    ##########################################################
    $conf->{datetime} = time2str("%C", time());
    $self->init_colorscheme($conf);

    ##########################################################
    # initialize directories
    ##########################################################
    my $metadir = $conf->{metadir};
    my $extsrcdir = $conf->{extsrcdir};
    my $targetdir = $conf->{targetdir};

    mkpath("$metadir");
    mkpath("$extsrcdir/htdocs/full");
    mkpath("$extsrcdir/htdocs/split");
    mkpath("$extsrcdir/images");

    ##########################################################
    # initialize files in docset directory
    ##########################################################
    $self->write_style_sheet($conf);
    $self->write_pods($conf);

}

sub generate_docset {
    my ($self, $conf) = @_;
    #use DocSet;

    ##########################################################
    # initialize variables
    ##########################################################
    $conf->{datetime} = time2str("%C", time());
    $self->init_colorscheme($conf);

    ##########################################################
    # initialize directories
    ##########################################################
    my $metadir = $conf->{metadir};
    my $extsrcdir = $conf->{extsrcdir};
    my $targetdir = $conf->{targetdir};

    mkpath("$metadir");
    mkpath("$extsrcdir/htdocs/full");
    mkpath("$extsrcdir/htdocs/split");
    mkpath("$extsrcdir/pdf");
    mkpath("$extsrcdir/lib");
    mkpath("$extsrcdir/images");
    mkpath("$extsrcdir/conf");

    ##########################################################
    # initialize files in docset directory
    ##########################################################
    $self->write_docset_config_file($conf);
    $self->write_style_sheet($conf);
    $self->write_pods($conf);

    $self->run_docset($conf);
}

##############################################################
# use Devel::Metadata
##############################################################

sub fix_module_html {
    my ($self, $conf, $module, $html_file, $relative_root, $dist_name, $dist_version) = @_;

    my $targetdir   = $conf->{targetdir};
    my $targeturl   = $conf->{targeturl};
    my $linkcolor   = $conf->{linkcolor};
    my $activecolor = $conf->{activecolor};

    my $modified = 0;
    my $html = $self->read_file($html_file);
    
    if ($html !~ m!HREF="$targeturl/! &&
        $html =~ s!HREF="/!HREF="$targeturl/!g) {
        $modified = 1;
    }
    
    my $unmodified_head = <<EOF;
<HTML[^<>]*>
<HEAD>
<TITLE>[^<>]*</TITLE>.*
</HEAD>

<BODY>
EOF

    if ($html =~ m/$unmodified_head/is) {

        my $title = "Module - $module";
        $dist_name ||= "unknown-dist";
        $dist_version ||= "0.00";
        my $top_navbar = $self->navbar("module", $dist_name, $dist_version, "unknown", "module", "main", "top", $relative_root);

        my $modified_head = <<EOF;
<HTML>
<HEAD>
  <TITLE>$title</TITLE>
  <LINK REL="stylesheet" HREF="$relative_root/style.css" TYPE="text/css">
  <SCRIPT>
    function asd() {
      parent.document.title="$module ($dist_name-$dist_version)";
    }
  </SCRIPT>
</HEAD>

<BODY bgcolor="white" link="$linkcolor" alink="$activecolor" vlink="$activecolor" onload="asd();">
$top_navbar
<hr>
<table border="0" cellspacing="0">
  <tr>
    <td valign=middle><img src="$relative_root/images/logo.gif" border="0"></td>
    <td valign=middle><h1>$module</h1></td>
  </tr>
</table>
EOF
        my $chg = $html =~ s!$unmodified_head!$modified_head!is;
        $modified = 1;
    }

    if ($modified) {
        $self->write_file($html_file,$html);
    }
}

sub run_docset {
    my ($self, $conf) = @_;
    $conf = $self->{conf} if (!$conf && ref($self));
    my $perl5lib = $ENV{PERL5LIB} || $ENV{PERLLIB};
    #my $lib = join ":", grep defined($_), "$Bin/../lib", $perl5lib;
    my $lib;
    my $extsrcdir = $conf->{extsrcdir};

    my $command = "env PERL5LIB=$lib docset_build -vd $extsrcdir lib/config.cfg";
    print "cmd [$command]\n";
    system $command;
}

sub init_colorscheme {
    my ($self, $conf) = @_;
    $conf = $self->{conf} if (!$conf && ref($self));
    my ($red, $green, $blue, $colorscheme);
    $colorscheme = $conf->{colorscheme};

    if    ($colorscheme eq "red")   { $red = 1; $green = 0; $blue = 0; }
    elsif ($colorscheme eq "green") { $red = 0; $green = 1; $blue = 0; }
    elsif ($colorscheme eq "blue")  { $red = 0; $green = 0; $blue = 1; }
    else                            { $red = 1; $green = 0; $blue = 0; }

    $conf->{bgcolor}       = "#FFFFFF" if (!$conf->{bgcolor});
    $conf->{menubgcolor}   = "#".($red?"FF":"CC").($green?"FF":"CC").($blue?"FF":"CC") if (!$conf->{menubgcolor});
    $conf->{vividbgcolor}  = "#".($red?"CC":"99").($green?"CC":"99").($blue?"CC":"99") if (!$conf->{vividbgcolor});
    $conf->{washedbgcolor} = "#".($red?"FF":"EE").($green?"FF":"EE").($blue?"FF":"EE") if (!$conf->{washedbgcolor});
    $conf->{linkcolor}     = "#".($red?"66":"00").($green?"66":"00").($blue?"66":"00") if (!$conf->{linkcolor});
    $conf->{activecolor}   = "#".($red?"99":"00").($green?"99":"00").($blue?"99":"00") if (!$conf->{activecolor});
    print "Colorscheme initialized [$colorscheme]\n" if ($conf->{verbose});
}

sub write_style_sheet {
    my ($self, $conf) = @_;
    $conf = $self->{conf} if (!$conf && ref($self));

    my $bgcolor       = $conf->{bgcolor};
    my $menubgcolor   = $conf->{menubgcolor};
    my $vividbgcolor  = $conf->{vividbgcolor};
    my $washedbgcolor = $conf->{washedbgcolor};
    my $linkcolor     = $conf->{linkcolor};
    my $activecolor   = $conf->{activecolor};
    my $targetdir        = $conf->{targetdir};

    my $css = <<EOF;
/* perldocs style sheet */

body {
    background-color: white;
    color: black;
}

/* because netscape 4 doesn't inherit from the body module we need to specify everything?!, gaah ... */
body, table, td, p, span, h1, h2, h3, ul {
    font-size: 10pt;
    font-family: Verdana, Helvetica, Arial, Univers, sans-serif
}

h1       { font-size: 155%; font-weight: bold; }
h2       { font-size: 125%; font-weight: bold; }
h3       { font-weight: bold; }

a:link   { color: $linkcolor; }
a:active { color: $activecolor; }
a:hover  { color: $linkcolor; }
a:vlink  { color: $activecolor; }

/* Table colors */
.TableHeadingColor     { background-color: $menubgcolor; }
.TableSubHeadingColor  { background-color: $vividbgcolor; }
.TableRowColor         { background-color: $bgcolor; }

/* Font used in left-hand frame lists */
.FrameTitleFont   {
    background-color: $menubgcolor;
    font-size: 12pt;
    font-weight: bold;
    font-family: Verdana, Helvetica, Arial, Univers, sans-serif;
}
.FrameHeadingFont {
    background-color: $menubgcolor;
    font-size: 12pt;
    font-weight: bold;
    font-family: Verdana, Helvetica, Arial, Univers, sans-serif;
}
.FrameItemFont    {
    font-size: 10pt;
    font-family: Verdana, Helvetica, Arial, Univers, sans-serif;
}

/* Navigation bar fonts and colors */
.NavBarCell1    { background-color: $menubgcolor; }
.NavBarCell1Rev { background-color: $activecolor; }
.NavBarFont1    { font-family: Verdana, Helvetica, Arial, Univers, sans-serif; color: $activecolor; }
.NavBarFont1Rev { font-family: Verdana, Helvetica, Arial, Univers, sans-serif; color: $menubgcolor; }

.NavBarCell2    { font-family: Verdana, Helvetica, Arial, Univers, sans-serif; background-color: $bgcolor; }
.NavBarCell3    { font-family: Verdana, Helvetica, Arial, Univers, sans-serif; background-color: $bgcolor; }

EOF
    $self->write_file("$targetdir/style.css", $css);
    print "Style sheet written [$targetdir/style.css]\n" if ($conf->{verbose});
}

sub navbar {
    my ($self, $type, $distribution, $version, $modulegroup, $module, $pagetype, $fileposition, $relative_root) = @_;
    #print "navbar($type, $distribution, $version, $modulegroup, $module, $pagetype, $fileposition, $relative_root)\n";

    my ($html, $plain_bgcolor, $highlight_bgcolor);
    my ($plain_cellstyle, $highlight_cellstyle);
    my ($plain_fontstyle, $highlight_fontstyle);
    my ($site_cellstyle, $dist_cellstyle, $modulegroup_cellstyle, $module_cellstyle, $use_cellstyle, $tree_cellstyle);
    my ($site_fontstyle, $dist_fontstyle, $modulegroup_fontstyle, $module_fontstyle, $use_fontstyle, $tree_fontstyle);
    my ($site_bgcolor,   $dist_bgcolor,   $modulegroup_bgcolor,   $module_bgcolor,   $use_bgcolor,   $tree_bgcolor);

    my $dmd = $self->{metadata};

    $plain_cellstyle       = "NavBarCell1";
    $highlight_cellstyle   = "NavBarCell1Rev";
    $plain_fontstyle       = "NavBarFont1";
    $highlight_fontstyle   = "NavBarFont1Rev";
    $plain_bgcolor         = $self->{conf}{washedbgcolor};
    $highlight_bgcolor     = $self->{conf}{bgcolor};

    $site_cellstyle        = $plain_cellstyle;
    $dist_cellstyle        = $plain_cellstyle;
    $modulegroup_cellstyle = $plain_cellstyle;
    $module_cellstyle      = $plain_cellstyle;
    $use_cellstyle         = $plain_cellstyle;
    $tree_cellstyle        = $plain_cellstyle;

    $site_fontstyle        = $plain_fontstyle;
    $dist_fontstyle        = $plain_fontstyle;
    $modulegroup_fontstyle = $plain_fontstyle;
    $module_fontstyle      = $plain_fontstyle;
    $use_fontstyle         = $plain_fontstyle;
    $tree_fontstyle        = $plain_fontstyle;

    $site_bgcolor          = $plain_bgcolor;
    $dist_bgcolor          = $plain_bgcolor;
    $modulegroup_bgcolor   = $plain_bgcolor;
    $module_bgcolor        = $plain_bgcolor;
    $use_bgcolor           = $plain_bgcolor;
    $tree_bgcolor          = $plain_bgcolor;

    if ($pagetype eq "use") {
        $use_cellstyle         = $highlight_cellstyle;
        $use_fontstyle         = $highlight_fontstyle;
        $use_bgcolor           = $highlight_bgcolor;
    }
    elsif ($pagetype eq "isa") {
        $tree_cellstyle        = $highlight_cellstyle;
        $tree_fontstyle        = $highlight_fontstyle;
        $tree_bgcolor          = $highlight_bgcolor;
    }
    elsif ($type eq "site") {
        $dist_cellstyle        = $highlight_cellstyle;
        $dist_fontstyle        = $highlight_fontstyle;
        $dist_bgcolor          = $highlight_bgcolor;
    }
    elsif ($type eq "distribution") {
        $dist_cellstyle        = $highlight_cellstyle;
        $dist_fontstyle        = $highlight_fontstyle;
        $dist_bgcolor          = $highlight_bgcolor;
    }
    elsif ($type eq "module") {
        $module_cellstyle      = $highlight_cellstyle;
        $module_fontstyle      = $highlight_fontstyle;
        $module_bgcolor        = $highlight_bgcolor;
        $distribution          = $dmd->module_def($module)->{distribution};
    }

    $html = <<EOF;
<!-- ========== START OF NAVBAR ========== -->
<A NAME="navbar_${fileposition}"><!-- --></A>
<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
  <TR>
    <TD COLSPAN=3 BGCOLOR="$plain_bgcolor" CLASS="$plain_cellstyle">
      <A NAME="navbar_${fileposition}_firstrow"><!-- --></A>
      <TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3" CLASS="$plain_cellstyle">
        <TR ALIGN="center" VALIGN="top">
          <TD BGCOLOR="$site_bgcolor" CLASS="$site_cellstyle">
            &nbsp;<A HREF="$relative_root/distribution/all/view.html"><FONT CLASS="$site_fontstyle"><B>Site</B></FONT></A>&nbsp;
          </TD>
          <TD BGCOLOR="$dist_bgcolor" CLASS="$dist_cellstyle">
            &nbsp;<A HREF="$relative_root/distribution/$distribution/view.html"><FONT CLASS="$dist_fontstyle"><B>Distribution</B></FONT></A>&nbsp;
          </TD>
          <TD BGCOLOR="$modulegroup_bgcolor" CLASS="$modulegroup_cellstyle">
            &nbsp;<FONT CLASS="$modulegroup_fontstyle">Module-Group</FONT>&nbsp;
          </TD>
          <TD BGCOLOR="$module_bgcolor" CLASS="$module_cellstyle">
            &nbsp;<FONT CLASS="$module_fontstyle"><B>Module</B></FONT>&nbsp;
          </TD>
          <TD BGCOLOR="$use_bgcolor" CLASS="$use_cellstyle">
            &nbsp;<FONT CLASS="$use_fontstyle">Use</FONT>&nbsp;
          </TD>
          <TD BGCOLOR="$tree_bgcolor" CLASS="$tree_cellstyle">
            &nbsp;<A HREF="$relative_root/view-tree-all.html"><FONT CLASS="$tree_fontstyle"><B>ISA</B></FONT></A>&nbsp;
          </TD>
        </TR>
      </TABLE>
    </TD>
    <TD ALIGN="right" VALIGN="top" ROWSPAN=3>
      <EM><b>$distribution-$version</b></EM>
    </TD>
  </TR>

  <TR>
    <TD BGCOLOR="white" CLASS="NavBarCell2">
      <FONT SIZE="-2">&nbsp;PREV&nbsp;&nbsp;NEXT</FONT>
    </TD>
    <TD BGCOLOR="white" CLASS="NavBarCell2">
      <FONT SIZE="-2">
        <A HREF="$relative_root/index.html" TARGET="_top"><B>FRAMES</B></A>&nbsp;&nbsp;
        <A HREF="$relative_root/view-a-all.html" TARGET="_top"><B>NO FRAMES</B></A>&nbsp;&nbsp;
        <SCRIPT>
          <!--
          if(window==top) {
            document.writeln('<A HREF="$relative_root/view-a-all.html" TARGET=""><B>All Modules</B></A>');
          }
          //-->
        </SCRIPT>
        <NOSCRIPT>
          <A HREF="$relative_root/view-a-all.html" TARGET=""><B>All Modules</B></A>
        </NOSCRIPT>
      </FONT>
    </TD>
  </TR>
</TABLE>
<!-- =========== END OF NAVBAR =========== -->
EOF

    $html;
}

sub html_file {
    my ($self, $type, $item, $frame, $values) = @_;
    my ($html_file);
    $type   ||= "site";    # site, distribution, module_group, module
    $item   ||= "all";
    $frame  ||= "view";    # contents, list, view
    $values ||= {};
    if ($type eq "site") {
        $html_file = "site/$frame.html";
        $values->{distribution} = "";
    }
    elsif ($type eq "distribution") {
        $html_file = "${type}/${item}/$frame.html";
        $values->{distribution} = $item;
    }
    elsif ($type eq "module") {  # should never happen (!)
        my $modulepath = $item;
        $modulepath =~ s!::!/!g;
        $html_file = "module/${modulepath}-$frame.html";
    }
    else {
        # should never happen
        warn "Warning: writing [$item] (type $type) contents\n";
        $html_file = "${type}/${item}/$frame.html";
    }
    my $relative_root = $html_file;
    $relative_root =~ s![^/]+!..!g;
    $relative_root =~ s!^\.\./?!!g;
    $relative_root .= "/" if ($relative_root);
    $values->{relative_root} = $relative_root;
    $values->{html_file} = $html_file;
    return($html_file);
}

sub write_frameset {
    my ($self, $type, $item) = @_;
    #print "write_frameset($type)\n";
    my $dmd = $self->{metadata};
    my $targetdir = $self->{conf}{targetdir};
    my $datetime = $self->{conf}{datetime};
    my $sitetitle = $self->{conf}{sitetitle};
    my $verbose = $self->{conf}{verbose};
    my ($html, $file, $relfile, $relative_root, @files, $modulepath);

    if ($type eq "site") {
        @files = ("index.html", "site/frameset.html");
    }
    elsif ($type eq "distribution") {
        @files = ("${type}/${item}-frameset.html");
    }
    elsif ($type eq "module") {
        $modulepath = $item;
        $modulepath =~ s!::!/!g;
        @files = ("module/${modulepath}-frameset.html");
    }
    else {
        # should never happen
        warn "Warning: writing a [$item] (type $type) frameset\n";
        @files = ("${type}/${item}-frameset.html");
    }

    foreach $file (@files) {
        $relative_root = $file;
        $relative_root =~ s![^/]+!..!g;
        $relative_root =~ s!^\.\./?!!g;
        $relative_root .= "/" if ($relative_root);
        $html = <<EOF;
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<HTML>
<HEAD>
  <!-- Generated by perldocs on $datetime -->
  <TITLE>$sitetitle</TITLE>
</HEAD>

<FRAMESET cols="20%,80%">
  <FRAMESET rows="40%,60%">
    <FRAME src="${relative_root}site/contents.html" name="contentsFrame">
    <FRAME src="${relative_root}site/list.html" name="listFrame">
  </FRAMESET>
  <FRAME src="${relative_root}site/view.html" name="viewFrame">
</FRAMESET>

<NOFRAMES>
<H2>Frame Alert</H2>
<P>
This document is designed to be viewed using the frames feature.
If you see this message, you are using a non-frame-capable web browser.
<BR>Link to<A HREF="view.html">Non-frame version.</A>
</NOFRAMES>
</HTML>
EOF
        $self->write_file("$targetdir/$file", $html);
    }
    my $numfiles = $#files + 1;
    print "$numfiles Framesets written.\n" if ($verbose);
}

sub write_contents {
    my ($self, $type, $item) = @_;
    my $dmd = $self->{metadata};
    my $targetdir = $self->{conf}{targetdir};
    my $datetime = $self->{conf}{datetime};
    my $sitetitle = $self->{conf}{sitetitle};
    my $linkcolor = $self->{conf}{linkcolor};
    my $activecolor = $self->{conf}{activecolor};

    my ($file, $modulepath, $relative_root);
    if ($type eq "site") {
        $file = "site/contents.html";
    }
    elsif ($type eq "distribution") {
        $file = "${type}/${item}-frameset.html";
    }
    elsif ($type eq "module") {
        $modulepath = $item;
        $modulepath =~ s!::!/!g;
        $file = "module/${modulepath}-frameset.html";
    }
    else {
        # should never happen
        warn "Warning: writing [$item] (type $type) contents\n";
        $file = "${type}/${item}-frameset.html";
    }
    $relative_root = $file;
    $relative_root =~ s![^/]+!..!g;
    $relative_root =~ s!^\.\./?!!g;
    $relative_root .= "/" if ($relative_root);

    my $html = <<EOF;
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<HTML>
<HEAD>
  <!-- Generated by perldocs on $datetime -->
  <TITLE>Overview ($sitetitle)</TITLE>
  <LINK REL="stylesheet" TYPE="text/css" HREF="${relative_root}style.css" TITLE="Style">
  <SCRIPT>
    function asd() {
      parent.document.title="Overview ($sitetitle)";
    }
  </SCRIPT>
</HEAD>
<BODY bgcolor="white" link="$linkcolor" alink="$activecolor" vlink="$activecolor" onload="asd();">

<TABLE BORDER="0" WIDTH="100%">
  <TR>
    <TD NOWRAP><FONT size="+1" CLASS="FrameTitleFont"><B>$sitetitle</B></FONT></TD>
  </TR>
</TABLE>

<TABLE BORDER="0" WIDTH="100%">
  <TR>
    <TD NOWRAP>
      <FONT CLASS="FrameItemFont"><A HREF="${relative_root}site/list.html" TARGET="listFrame">All Classes</A></FONT><P>
      <FONT size="+1" CLASS="FrameHeadingFont">Distributions</FONT><BR>
EOF

    my ($distribution);
    foreach $distribution (@{$self->{distributions}}) {
        $html .= <<EOF;
      <FONT CLASS="FrameItemFont"><A HREF="${relative_root}distribution/${distribution}/list.html" TARGET="listFrame">$distribution</A></FONT><BR>
EOF
    }

    $html .= <<EOF;
    </TD>
  </TR>
</TABLE>

<P>
&nbsp;
</BODY>
</HTML>
EOF
    $self->write_file("$targetdir/$file", $html);
}

sub write_list {
    my ($self, $type, $item, $title) = @_;
    my $dmd = $self->{metadata};
    my $datetime = $self->{conf}{datetime};
    my $targetdir = $self->{conf}{targetdir};
    my $linkcolor = $self->{conf}{linkcolor};
    my $activecolor = $self->{conf}{activecolor};

    my ($distribution, $html_file, $modulepath, $relative_root, $short_title);
    if (!$title) {
        $title = ucfirst($type);
        $title .= " - $item" if ($item);
    }
    $short_title = $item;
    $short_title = "Site" if (!$short_title);

    if ($type eq "site") {
        $html_file = "site/list.html";
        $distribution = undef;
    }
    elsif ($type eq "distribution") {
        $html_file = "${type}/${item}/list.html";
        $distribution = $item;
    }
    elsif ($type eq "module") {  # should never happen (!)
        $modulepath = $item;
        $modulepath =~ s!::!/!g;
        $html_file = "module/${modulepath}-list.html";
    }
    else {
        # should never happen
        warn "Warning: writing [$item] (type $type) contents\n";
        $html_file = "${type}/${item}/list.html";
    }
    $relative_root = $html_file;
    $relative_root =~ s![^/]+!..!g;
    $relative_root =~ s!^\.\./?!!g;
    $relative_root .= "/" if ($relative_root);

    my $html = <<EOF;
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<HTML>
<HEAD>
  <!-- Generated by perldocs on $datetime -->
  <TITLE>$title</TITLE>
  <LINK REL="stylesheet" HREF="${relative_root}style.css" TYPE="text/css">
  <SCRIPT>
    function asd() {
      parent.document.title="$title";
    }
  </SCRIPT>
</HEAD>
<BODY bgcolor="white" link="$linkcolor" alink="$activecolor" vlink="$activecolor" onload="asd();">

<TABLE BORDER="0" WIDTH="100%">
  <TR>
    <TD NOWRAP><FONT CLASS="FrameItemFont">
      <FONT size="+1" CLASS="FrameHeadingFont"><B>$short_title</B></FONT><P>
EOF
    my ($htmlfile, $is_doc, $doc_html, $doc_nonimp_html, $module_html, $module_nonimp_html, $module, $module_def);
    my ($files, $file, $files_html, $shortfile);

    $doc_html = "";
    $doc_nonimp_html = "";
    $module_html = "";
    $module_nonimp_html = "";

    foreach $module (sort $dmd->modules($item)) {
        $htmlfile = "${relative_root}module/$module.html";
        $htmlfile =~ s!::!/!g;

        $is_doc = 0;

        # TODO: fix up these rules
        if ($module =~ /^[a-z]/) {
            $is_doc = 1;
        }
        elsif ($module =~ /::/) {
            $is_doc = 0;
        }
        elsif ($module =~ /^[A-Z][a-zA-Z0-9]*$/) {
            $is_doc = 0;
        }
        else {
            $is_doc = 1;
        }

        if ($is_doc) {
            $doc_html .= <<EOF;
          <A HREF="$htmlfile" TARGET="viewFrame">$module</A><BR>
EOF
        }
        else {
#            $module_def = $dmd->module_def($module);
#            #print "module=$module def={", join(",", %$module_def), "}\n";
#            $file = $module_def->{pmfile};
#            if ($file) {
#                $module_html .= <<EOF;
#          <A HREF="file:$file.html" TARGET="viewFrame">F</A>
#EOF
#            }
             $module_html .= <<EOF;
         <A HREF="$htmlfile" TARGET="viewFrame">$module</A><BR>
EOF
        }
    }

    $files = $dmd->{$type}{$item}{files};
    if (ref($files) eq "ARRAY") {
        foreach $file (sort @$files) {
            $shortfile = &file2shortfile($file);
            $files_html .= <<EOF;
         <A HREF="file$file.html" TARGET="viewFrame">$shortfile</A><BR>
EOF
        }
    }

    if ($doc_html) {
        $html .= <<EOF;
      <FONT size="+0" CLASS="xFrameHeadingFont"><B>Documents</B></FONT><BR>
$doc_html
<p>
EOF
    }

    if ($module_html) {
        $html .= <<EOF;
      <FONT size="+0" CLASS="xFrameHeadingFont"><B>Modules</B></FONT><BR>
$module_html
<p>
EOF
    }

    if ($doc_nonimp_html) {
        $html .= <<EOF;
      <FONT size="+0" CLASS="xFrameHeadingFont"><B>Documents (planned)</B></FONT><BR>
$doc_nonimp_html
<p>
EOF
    }

    if ($module_nonimp_html) {
        $html .= <<EOF;
      <FONT size="+0" CLASS="xFrameHeadingFont"><B>Modules (planned)</B></FONT><BR>
$module_nonimp_html
<p>
EOF
    }

    if ($files_html) {
        $html .= <<EOF;
      <FONT size="+0" CLASS="xFrameHeadingFont"><B>Files</B></FONT><BR>
$files_html
<p>
EOF
    }

    $html .= <<EOF;
    </FONT></TD>
  </TR>
</TABLE>

</BODY>
</HTML>
EOF

    $self->write_file("$targetdir/$html_file", $html);
}

sub file2shortfile {
    my ($file) = @_;
    my $shortfile = $file;
    $shortfile =~ s!.*/!!;
    return($shortfile);
}

sub write_view_a {
    my ($self, $type, $item, $title) = @_;
    my $dmd = $self->{metadata};
    my $bgcolor = $self->{conf}{bgcolor};
    my $menubgcolor = $self->{conf}{menubgcolor};
    my $washedbgcolor = $self->{conf}{washedbgcolor};
    my $linkcolor = $self->{conf}{linkcolor};
    my $activecolor = $self->{conf}{activecolor};
    my $targetdir = $self->{conf}{targetdir};
    my $relative_root = ".";
    my ($html);
    $title = $item if (!$title);
    my $ctype = substr($type,0,1);
    $html = <<EOF;
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<!--NewPage-->
<HTML>
<HEAD>
  <!-- Generated by javadoc on Wed Oct 10 20:02:45 PDT 2001 -->
  <TITLE>Overview ($title)</TITLE>
  <LINK REL="stylesheet" HREF="${relative_root}/style.css" TYPE="text/css">
  <SCRIPT>
    function asd() {
      parent.document.title="Overview ($title)";
    }
  </SCRIPT>
</HEAD>
<BODY bgcolor="white" link="$linkcolor" alink="$activecolor" vlink="$activecolor" onload="asd();">

<!-- ========== START OF NAVBAR ========== -->
<A NAME="navbar_top"><!-- --></A>
<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
  <TR>
    <TD COLSPAN=3 BGCOLOR="$washedbgcolor" CLASS="NavBarCell1">
      <A NAME="navbar_top_firstrow"><!-- --></A>
      <TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
        <TR ALIGN="center" VALIGN="top">
          <TD BGCOLOR="$bgcolor" CLASS="NavBarCell1Rev">&nbsp;
            <FONT CLASS="NavBarFont1Rev"><B>Overview</B></FONT>&nbsp;
          </TD>
          <TD BGCOLOR="$washedbgcolor" CLASS="NavBarCell1">
            <FONT CLASS="NavBarFont1">Class-Group</FONT>&nbsp;
          </TD>
          <TD BGCOLOR="$washedbgcolor" CLASS="NavBarCell1">
            <FONT CLASS="NavBarFont1">Class</FONT>&nbsp;
          </TD>
          <TD BGCOLOR="$washedbgcolor" CLASS="NavBarCell1">
            <FONT CLASS="NavBarFont1">Use</FONT>&nbsp;
          </TD>
          <TD BGCOLOR="$washedbgcolor" CLASS="NavBarCell1">
            <A HREF="view-tree-$item.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;
          </TD>
        </TR>
      </TABLE>
    </TD>
    <TD ALIGN="right" VALIGN="top" ROWSPAN=3>
      <EM><b>$title</b></EM>
    </TD>
  </TR>

  <TR>
    <TD BGCOLOR="white" CLASS="NavBarCell2">
      <FONT SIZE="-2">&nbsp;PREV&nbsp;&nbsp;NEXT</FONT>
    </TD>
    <TD BGCOLOR="white" CLASS="NavBarCell2">
      <FONT SIZE="-2">
        <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A>&nbsp;&nbsp;
        <A HREF="view-$item.html" TARGET="_top"><B>NO FRAMES</B></A>&nbsp;&nbsp;
        <SCRIPT>
          <!--
          if(window==top) {
            document.writeln('<A HREF="view-a-all.html" TARGET=""><B>All Classes</B></A>');
          }
          //-->
        </SCRIPT>
        <NOSCRIPT>
        <A HREF="view-a-all.html" TARGET=""><B>All Classes</B></A>
        </NOSCRIPT>
      </FONT>
    </TD>
  </TR>
</TABLE>
<!-- =========== END OF NAVBAR =========== -->

<HR>
<CENTER>
<H2>$title</H2>
</CENTER>
This is the Perl documentation for $title.
<P>

<!--
<B>See:</B>
<BR>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="#overview_description"><B>Description</B></A>
<P>
-->

<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
<TR BGCOLOR="$menubgcolor" CLASS="TableHeadingColor">
<TD COLSPAN=2><FONT SIZE="+2">
<B>Distributions</B></FONT></TD>
</TR>
EOF

    my ($distribution, $description, $url);
    foreach $distribution (sort keys %{$dmd->{distribution}}) {
        $description = $dmd->{distribution}{$distribution}{description};
        $description = "The $distribution distribution." if (!$description);
        $url = "view-d-$distribution.html";
        $html .= <<EOF;
<TR BGCOLOR="white" CLASS="TableRowColor">
<TD><B><A HREF="$url">$distribution</A></B></TD>
<TD>$description</TD>
</TR>
EOF
    }

    $html .= <<EOF;
</TABLE>

<P>
&nbsp;<A NAME="overview_description"><!-- --></A>
<P>
This is the Perl documentation for $title.
<p>
<P>

<P>
<HR>

<!-- ========== START OF NAVBAR ========== -->
<A NAME="navbar_bottom"><!-- --></A>
<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
<TR>
<TD COLSPAN=3 BGCOLOR="$washedbgcolor" CLASS="NavBarCell1">
<A NAME="navbar_bottom_firstrow"><!-- --></A>
<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
  <TR ALIGN="center" VALIGN="top">
  <TD BGCOLOR="$bgcolor" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Overview</B></FONT>&nbsp;</TD>
  <TD BGCOLOR="$washedbgcolor" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Class-Group</FONT>&nbsp;</TD>
  <TD BGCOLOR="$washedbgcolor" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Class</FONT>&nbsp;</TD>
  <TD BGCOLOR="$washedbgcolor" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Use</FONT>&nbsp;</TD>
  <TD BGCOLOR="$washedbgcolor" CLASS="NavBarCell1">    <A HREF="view-tree-$item.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
  </TR>
</TABLE>
</TD>
<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
<b>$title</b></EM>
</TD>
</TR>

<TR>
<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
&nbsp;PREV&nbsp;
&nbsp;NEXT</FONT></TD>
<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
  <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A>  &nbsp;
&nbsp;<A HREF="view-$item.html" TARGET="_top"><B>NO FRAMES</B></A>  &nbsp;
&nbsp;
<SCRIPT>
  <!--
  if(window==top) {
    document.writeln('<A HREF="view-a-all.html" TARGET=""><B>All Classes</B></A>');
  }
  //-->
</SCRIPT>
<NOSCRIPT>
<A HREF="view-a-all.html" TARGET=""><B>All Classes</B></A>
</NOSCRIPT>
</FONT></TD>
</TR>
</TABLE>
<!-- =========== END OF NAVBAR =========== -->

</BODY>
</HTML>
EOF
    $self->write_file("$targetdir/view-$ctype-$item.html", $html);
}

sub write_view_use {
    my ($self) = @_;
    my $dmd = $self->{metadata};
}

sub class_group_tree {
    my ($dmd, $class_group) = @_;
    my $html = "";
    return($html);
}

sub write_view_tree {
    my ($self) = @_;
    my $dmd = $self->{metadata};
    $self->write_view_tree_any("all");
    my ($class_group);
    foreach $class_group (sort keys %{$dmd->{classgroup}}) {
        $self->write_view_tree_any($class_group);
    }
}

sub write_view_tree_any {
    my ($self, $this_class_group) = @_;
    my $dmd           = $self->{metadata};
    my $bgcolor       = $self->{conf}{bgcolor};
    my $washedbgcolor = $self->{conf}{washedbgcolor};
    my $linkcolor     = $self->{conf}{linkcolor};
    my $activecolor   = $self->{conf}{activecolor};
    my $datetime      = $self->{conf}{datetime};
    my $targetdir     = $self->{conf}{targetdir};
    my $relative_root = ".";
    my ($html, $title);
    $title = ($this_class_group eq "all") ? "All Class Groups" : "$this_class_group Class Group";
    $html = <<EOF;
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<!--NewPage-->
<HTML>
<HEAD>
  <!-- Generated by perldocs on $datetime -->
  <TITLE>Class Hierarchy ($title)</TITLE>
  <LINK REL="stylesheet" HREF="${relative_root}/style.css" TYPE="text/css">
  <SCRIPT>
    function asd() {
      parent.document.title="Class Hierarchy ($title)";
    }
  </SCRIPT>
</HEAD>
<BODY bgcolor="white" link="$linkcolor" alink="$activecolor" vlink="$activecolor" onload="asd();">

<!-- ========== START OF NAVBAR ========== -->
<A NAME="navbar_top"><!-- --></A>
<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
<TR>
<TD COLSPAN=3 BGCOLOR="$washedbgcolor" CLASS="NavBarCell1">
<A NAME="navbar_top_firstrow"><!-- --></A>
<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
  <TR ALIGN="center" VALIGN="top">
  <TD BGCOLOR="$washedbgcolor" CLASS="NavBarCell1">    <A HREF="view-a-all.html"><FONT CLASS="NavBarFont1"><B>Overview</B></FONT></A>&nbsp;</TD>
  <TD BGCOLOR="$washedbgcolor" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Class-Group</FONT>&nbsp;</TD>
  <TD BGCOLOR="$washedbgcolor" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Class</FONT>&nbsp;</TD>
  <TD BGCOLOR="$washedbgcolor" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Use</FONT>&nbsp;</TD>
  <TD BGCOLOR="$bgcolor" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Tree</B></FONT>&nbsp;</TD>
  </TR>
</TABLE>
</TD>
<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
<b>$title</b></EM>
</TD>
</TR>

<TR>
<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
&nbsp;PREV&nbsp;
&nbsp;NEXT</FONT></TD>
<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
  <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A>  &nbsp;
&nbsp;<A HREF="view-tree-all.html" TARGET="_top"><B>NO FRAMES</B></A>  &nbsp;
&nbsp;
<SCRIPT>
  <!--
  if(window==top) {
    document.writeln('<A HREF="view-a-all.html" TARGET=""><B>All Classes</B></A>');
  }
  //-->
</SCRIPT>
<NOSCRIPT>
<A HREF="view-a-all.html" TARGET=""><B>All Classes</B></A>
</NOSCRIPT>
</FONT></TD>
</TR>
</TABLE>
<!-- =========== END OF NAVBAR =========== -->

<HR>
<CENTER>
<H2>
Hierarchy For $title</H2>
</CENTER>
<DL>
<DT>
    <B>Class Group Hierarchies:</B><DD>
EOF

    my ($class_group);
    if ($this_class_group eq "all") {
        foreach $class_group (sort keys %{$dmd->{classgroup}}) {
            if ($class_group ne "all") {
                $html .= "   <A HREF=\"${class_group}-tree.html\">$class_group</A>,\n";
            }
            else {
                $html .= "   <A HREF=\"view-tree-all.html\">All Classes</A>\n";
            }
        }
    }
    else {
        $html .= "   <A HREF=\"view-tree-all.html\">All Classes</A>\n";
    }

    $html .= <<EOF;
</DD>
</DT>
</DL>
<HR>
<H2>
Class Hierarchy
</H2>
EOF

    $html .= &class_group_tree($dmd, $this_class_group);

    $html .= <<EOF;
<HR>

<!-- ========== START OF NAVBAR ========== -->
<A NAME="navbar_bottom"><!-- --></A>
<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
<TR>
<TD COLSPAN=3 BGCOLOR="$washedbgcolor" CLASS="NavBarCell1">
<A NAME="navbar_bottom_firstrow"><!-- --></A>
<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
  <TR ALIGN="center" VALIGN="top">
  <TD BGCOLOR="$washedbgcolor" CLASS="NavBarCell1">    <A HREF="view-a-all.html"><FONT CLASS="NavBarFont1"><B>Overview</B></FONT></A>&nbsp;</TD>
  <TD BGCOLOR="$washedbgcolor" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Class-Group</FONT>&nbsp;</TD>
  <TD BGCOLOR="$washedbgcolor" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Class</FONT>&nbsp;</TD>
  <TD BGCOLOR="$washedbgcolor" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Use</FONT>&nbsp;</TD>
  <TD BGCOLOR="$bgcolor" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Tree</B></FONT>&nbsp;</TD>
  </TR>
</TABLE>

</TD>
<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
<b>$title</b></EM>
</TD>
</TR>

<TR>
<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
&nbsp;PREV&nbsp;
&nbsp;NEXT</FONT></TD>
<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
  <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A>  &nbsp;
&nbsp;<A HREF="view-tree-all.html" TARGET="_top"><B>NO FRAMES</B></A>  &nbsp;
&nbsp;
<SCRIPT>
  <!--
  if(window==top) {
    document.writeln('<A HREF="view-a-all.html" TARGET=""><B>All Classes</B></A>');
  }
  //-->
</SCRIPT>
<NOSCRIPT>
<A HREF="view-a-all.html" TARGET=""><B>All Classes</B></A>
</NOSCRIPT>
</FONT></TD>
</TR>
</TABLE>
<!-- =========== END OF NAVBAR =========== -->

</BODY>
</HTML>
EOF

    if ($this_class_group eq "all") {
        $self->write_file("$targetdir/view-tree-all.html", $html);
    }
    else {
        $self->write_file("$targetdir/${this_class_group}-tree.html", $html);
    }
}

sub write_docset_config_file {
    my ($self, $conf) = @_;
    $conf = $self->{conf} if (!$conf && ref($self));

    my $extsrcdir = $conf->{extsrcdir};
    my $templatedir = $conf->{templatedir};

    local(*main::FILE);
    open(main::FILE, "> $extsrcdir/lib/config.cfg") || die "Unable to open $extsrcdir/lib/config.cfg: $!\n";
    print main::FILE <<EOF;
use vars qw(\@c);
\@c = (
     id => 'home',
     title => "Home",
     abstract => '',

     #body => {
     #    top => 'index_top.html',
     #    bot => 'index_bot.html',
     #},
     
     #docsets =>  ['docs'],
     #chapters => [
     #    qw(
     #       about/about.html
     #      )
     #],
     #docsets => [
     #    qw(
     #       download
     #      )
     #],

     #success
     #links => [
     #    {
     #     id       => 'asf',
     #     link     => 'http://apache.org/foundation/projects.html',
     #     title    => 'The ASF Projects',
     #     abstract => "There many other ASF Projects",
     #    },
     #],

     # non-pod/html files or dirs to be copied unmodified
     copy_glob => [
         qw(
            style.css
            images/*
           )
     ],

     copy_skip => [
         '(?:^|\\/)CVS(?:\\/|\$)', # skip cvs control files
         '#|~',                 # skip emacs backup files
     ],

     dir => {
 	     # the resulting html files directory
 	     dst_html   => "htdocs/full",
 	     
 	     # the resulting ps and pdf files directory (and special
 	     # set of html files used for creating the ps and pdf
 	     # versions.)
 	     dst_ps     => "pdf",
 	     
 	     # the resulting split version html files directory
 	     dst_split_html => "htdocs/split",
 	     
             # location of the templates (searched left to right)
             tmpl       => ["$templatedir/custom", "$templatedir/std", "$templatedir"],

             # search path for pods, etc. must put more specific paths first!
             search_paths => [qw(
                 .
              )],

              # what extensions to search for
              search_exts => [qw(pod pm html)],
 	    },	

     file => {
	      
	      # the html2ps configuration file
	      html2ps_conf  => "conf/html2ps.conf",
	      
	     },
     
    mode => {
#	      # you can override the directories creation mode
#	      dir      => 0755,
#	     },

    );

1;

EOF
    close(main::FILE);
}

sub read_file {
    my ($self, $file) = @_;
    local(*main::FILE);
    my ($data, @data);
    #print "Reading [$file] ...\n";
    if (open(main::FILE, "< $file")) {
        @data = <main::FILE>;
        close(main::FILE);
        return (@data) if (wantarray);
        $data = join("", @data);
        return ($data);
    }
    else {
        print "Failed to open file for reading [$file]: $!\n";
    }
    return("");
}

sub write_file {
    my ($self, $file, $data) = @_;
    #print "write_file($file,...)\n";
    my $dir = dirname($file);
    mkpath($dir) if (! -d $dir);
    local(*main::FILE);
    if (open(main::FILE, "> $file")) {
        print main::FILE $data;
        close(main::FILE);
        #print "Writing [$file] ...\n";
    }
    else {
        print "Failed to open file for writing [$file]: $!\n";
    }
}

1;
 
